package com.seteam.collabcrossword;

import com.seteam.collabcrossword.messages.Message;
import com.seteam.collabcrossword.messages.client.*;
import com.seteam.collabcrossword.messages.generic.UpdateLetter;
import com.seteam.collabcrossword.messages.server.CrosswordAndClues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;

/**
 * This class parses the messages sent by the client to the server. After
 * parsing the messages the class also handles the the processing of the
 * information received from the client.
 * 
 * @author SE TEam
 * 
 */
public class MessageParser {
	private final Logger logger = LoggerFactory.getLogger(MessageParser.class);
	Resources resources = null;

	/**
	 * Constructor of MessageParser. We take in an instance of the Shared
	 * resource which will be accessed from the message parser.
	 * 
	 * @param resources
	 */
	public MessageParser(Resources resources) {
		try {
			this.resources = resources;
		} catch (Exception e) {
			logger.error("Exception e", e.getMessage());
		}

	}

	/**
	 * Parses the "Connect" message containing client IP to be able to connect
	 * to the client.
	 * 
	 * @param connect
	 *            Connect type object.
	 */
	public InetAddress parseMessage(final Connect connect) {
		// TODO Figure out if connect message is required.
		return connect.getClientIP();

	}

	/**
	 * Gets the crossword board along with the clues.
	 * 
	 * @param getBoard
	 *            GetBoard type message.
	 * @return CrosswordAndClues object, which contains the Crossword and Clues.
	 */
	public CrosswordAndClues parseMessage(final GetBoard getBoard) {
		// Get the crossword valiable
		CrosswordAndClues crossword = null;

		// STEP 1: Are two clients connected
		// This is done by using barrier wait, where using the barrier two
		// threads waits for
		try {
			logger.info("Trying to get the board");
			crossword = resources.getCrossword();

		} catch (Exception e) {
			logger.error("Exception: {}", e.getMessage());
		}

		return crossword;
	}

	/**
	 * Releases the locks a client has on any of the objects when he wants to
	 * quit the game.
	 * 
	 * @param quit
	 *            Message of type Quit.
	 */
	public void parseMessage(final Quit quit) {
		// Release the locks held by all the client.
		resources.releaseLocks();
	}

	/**
	 * Request the lock for a word. Based on the where the lock should begin and
	 * the direction the lock should be obtained, the lock request is processed.
	 * 
	 * @param requestLock
	 *            Message of type RequestLock. Contains the direction in which
	 *            the lock should be acquired and the Coordinate of the Tile
	 *            from where the locking of the word should start.
	 * @return Message
	 */
	public Message parseMessage(final RequestLock requestLock) {
		final Message response = resources.lockWord(
				requestLock.getStartOfWord(), requestLock.getDirection());
		return response;
	}

	/**
	 * Updates the letter entered by any of the two clients in the servers copy
	 * of the Crossword so that the current state is maintaind.
	 * 
	 * @param updateLetter
	 *            Message of type UpdateLetter.
	 */
	public void parseMessage(final UpdateLetter updateLetter) {
		try {
			resources.updateLetter(updateLetter.getTile());

		} catch (Exception e) {
			logger.error("Exception {}", e.getMessage());
		}

	}

	/**
	 * This method is called when the client submits his answer to the server
	 * once the Crossword is completely filled.
	 * 
	 * @param checkSolution
	 *            Message of type CheckSolution.
	 * @return CrosswordCurrentState, which is the current state of the
	 *         crossword maintained in the server.
	 */
	public CrosswordCurrentState parseMessage(final CheckSolution checkSolution) {
		CrosswordCurrentState crosswordCurrent = null;
		try {
			crosswordCurrent = resources.getCrosswordCurrent();

		} catch (Exception e) {
			logger.error("Exception {}", e.getMessage());
		}

		return crosswordCurrent;
	}

	/**
	 * Method used by DataReceiver to get the Crossword Solution.
	 * 
	 * @return CrosswordSolution object, containing the solutio to the
	 *         crossword.
	 */
	public CrosswordSolution getCrosswordSolution() {
		CrosswordSolution crosswordSolution = null;
		try {
			crosswordSolution = resources.getCrosswordSolution();
		} catch (Exception e) {
			logger.error("Exception {}", e.getMessage());
		}

		return crosswordSolution;
	}
}
